#include "aerial\Game\GameObject\FlyObject\Fighter.h"

#include "aerial\Game\GameObject\Equipment\Shield.h"
#include "aerial\Game\GameObject\Equipment\Propeller.h"
#include "aerial\Game\GameObject\Equipment\VulcanEquip.h"

#include <iostream>

using namespace std;

const float Fighter::SpeedPowerGen = 3.f;
const float Fighter::MaxArmor = 40.f;
const float Fighter::MaxPower = 100.f;

const float Fighter::MaxShieldRadius = 2.8f;
const float Fighter::RadiusPS = 2.f;
const float Fighter::MPPS = 400.f;

Fighter::Fighter(int id, const char* username, float x, float y, uchar side, float A)
	: FlyObject(x, y, A, id, username, side), vulcanEquip(0),lastArmor(armor),judge(0) {
	power = MaxPower;
	armor = MaxArmor;
	vulcanEquip = new VulcanEquip(world, this);

	b2CircleShape circle;
	circle.m_radius = 0.5f;

	b2FixtureDef fixtureDef;
	fixtureDef.shape = &circle;
	fixtureDef.density = 1.f;
	fixtureDef.friction = 1.f;
	fixtureDef.restitution = .1f;
	body->SetLinearDamping(1.f);

	body->CreateFixture(&fixtureDef);

	shield = new Shield(MaxShieldRadius, this);
	spr = hgeResMan->GetSprite("spr.fighter");
	propeller = new Propeller(this, 1.f, 0.f);
}

Fighter::~Fighter() {
	delete vulcanEquip;
}

void Fighter::render()
{
	if (!toDestroy) {
		if (judge)
			spr->SetColor(0xffff0000);
		else
			spr->SetColor(0xffffffff);

		spr->RenderEx(T.x, T.y, A, 0.2f, 0.2f);
		shield->renderShield(T.x, T.y);
		propeller->rendPropeller();
		vulcanEquip->renderVulcan();
	}
	if (side != MeSide)	fnt->SetColor(0xffff0000);
	else fnt->SetColor(0xffffffff);
	fnt->printf(T.x, T.y, HGETEXT_LEFT, "%s", username);
}

bool Fighter::update(float dt)
{
	// power regeneration
	power += SpeedPowerGen * dt;
	if (power > MaxPower) power = MaxPower;

	move(dt);	// action move
	turn(dt);	// action rotate
	HandleVulcan(dt);

	lastArmor = armor;
	// flyobject dealing with general equipment and network deviation
	FlyObject::update(dt);
	return false;
}

void Fighter::move(float dt)
{
	if (lastArmor != armor)
		judge = 1;
	else
		judge = 0;;
	int m = status & F_M_MOV;
	if (m) {
		b2Vec2 v(
			GetDirection().x * MPPS / BattleHelper::getRatio(),
			GetDirection().y * MPPS / BattleHelper::getRatio()
		);
		SetSpeed(v); 
	}
}

void Fighter::turn(float dt)
{
	int r = status & (F_M_ROT);
	if (r == F_V_CROT) 
	{
		Rotate(RadiusPS * dt); 
		float v = GetSpeed().Length();
		b2Vec2 vD(GetDirection().x * v, GetDirection().y * v);
		SetSpeed(vD);
	}
	else if (r == F_V_CCROT) 
	{
		Rotate(-RadiusPS * dt);
		float v = GetSpeed().Length();
		b2Vec2 vD(GetDirection().x * v, GetDirection().y * v);
		SetSpeed(vD);
	}
}

void Fighter::HandleVulcan(float dt)
{
	int v = status & F_V_VULCAN;
	if (v == F_V_VULCAN)
	{
		SetSpeed(b2Vec2(0.f, 0.f));
		if (!vulcanEquip->isOn()) vulcanEquip->start();
	}
	else 
	{
		vulcanEquip->stop();
	}
	vulcanEquip->update(dt);
}

void Fighter::processInput()
{
	float offsetX, offsetY;
	if ( T.x < 400 ) offsetX = 0.f;
	else if ( T.x < 3440 ) offsetX = T.x - 400.f;
	else offsetX = 3040.f;

	if (T.y < 300) offsetY = 0.f;
	else if (T.y < 780) offsetY = T.y - 300.f;
	else offsetY = 480.f;

	hge->Input_GetMousePos(&lastX, &lastY);
	lastX += offsetX;
	lastY += offsetY;

	while (hge->Input_GetEvent(inputEvent))
	{
		switch (inputEvent->key)
		{
		case HGEK_A:
			if (inputEvent->type == INPUT_KEYDOWN) {
				if (!vulcanEquip->isOn()) SetState(F_V_CCROT, F_M_ROT);
			}	 
			else SetState(0, F_V_CCROT);
			break;
		case HGEK_D:
			if (inputEvent->type == INPUT_KEYDOWN) 
			{
				if (!vulcanEquip->isOn()) SetState(F_V_CROT, F_M_ROT);
			}
			else SetState(0, F_V_CROT);
			break;
		case HGEK_W:
			if (inputEvent->type == INPUT_KEYDOWN) 
			{
				if (!vulcanEquip->isOn())
				{
					SetState(F_M_MOV, F_M_MOV); 
				}
			}
			else SetState(0, F_M_MOV);
			break;
		case HGEK_RBUTTON:
			if (inputEvent->type == INPUT_MBUTTONDOWN) 
			{
				if (Shield::available(this)) {
					SetState(M_SHIELD, M_SHIELD);
				}
			}
			else SetState(0, M_SHIELD);
			break;
		case HGEK_LBUTTON:
			
				if (inputEvent->type == INPUT_MBUTTONDOWN)
				{
					if (vulcanEquip->available()) {
						SetState(F_V_VULCAN, F_M_VULCAN);
					}
				}
				else SetState(0, F_V_VULCAN);
			break;				
		}
	}
}
